/*
 *  Copyright 2005 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.persistence.hibernate.forum;

import com.blandware.atleap.common.util.PartialCollection;
import com.blandware.atleap.common.util.QueryInfo;
import com.blandware.atleap.model.core.User;
import com.blandware.atleap.model.forum.Forum;
import com.blandware.atleap.model.forum.ForumSubscription;
import com.blandware.atleap.model.forum.Topic;
import com.blandware.atleap.persistence.forum.ForumSubscriptionDAO;
import com.blandware.atleap.persistence.hibernate.core.BaseDAOHibernate;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * <p>Hibernate implementation of ForumSubscriptionDAO.</p>
 * <p><a href="ForumSubscriptionDAOHibernate.java.html"><i>View source</i></a></p>
 *
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.3 $ $Date: 2008/06/23 13:24:54 $
 */
public class ForumSubscriptionDAOHibernate extends BaseDAOHibernate
        implements ForumSubscriptionDAO {

    // ~ CRUD Methods ================================================================

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#createForumSubscription(com.blandware.atleap.model.forum.ForumSubscription, com.blandware.atleap.model.forum.Forum, com.blandware.atleap.model.forum.Topic, com.blandware.atleap.model.core.User)
     */
    public Long createForumSubscription(ForumSubscription forumSubscription, Forum forum, Topic topic, User user) {
        if (forum != null) {
            forum.addForumSubscription(forumSubscription);
        } else {
            forumSubscription.setForum(forum);
        }
        if (topic != null) {
            topic.addForumSubscription(forumSubscription);
        } else {
            forumSubscription.setTopic(topic);
        }
        forumSubscription.setUser(user);
        return (Long) getHibernateTemplate().save(forumSubscription);
    }

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#retrieveForumSubscription(Long)
     */
    public ForumSubscription retrieveForumSubscription(Long id) {
        String hql = new StringBuffer("select fs from ForumSubscription as fs ")
                .append("where fs.id = ? ")
                .toString();
        return (ForumSubscription) findUniqueResult(hql, new Object[]{id});
    }

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#updateForumSubscription(com.blandware.atleap.model.forum.ForumSubscription)
     */
    public void updateForumSubscription(ForumSubscription forumSubscription) {
        getHibernateTemplate().update(forumSubscription);
    }

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#deleteForumSubscription(com.blandware.atleap.model.forum.ForumSubscription)
     */
    public void deleteForumSubscription(ForumSubscription forumSubscription) {
        if (forumSubscription.getForum() != null) {
            forumSubscription.getForum().removeForumSubscription(forumSubscription);
        }
        if (forumSubscription.getTopic() != null) {
            forumSubscription.getTopic().removeForumSubscription(forumSubscription);
        }
        getHibernateTemplate().delete(forumSubscription);
    }

    // ~ Additional methods ================================================================

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#listForumSubscriptions(com.blandware.atleap.common.util.QueryInfo)
     */
    public PartialCollection listForumSubscriptions(QueryInfo queryInfo) {
		String whereClause = new String();
		String orderByClause = new String();
		if ( queryInfo != null ) {
			whereClause = queryInfo.getWhereClause();
			orderByClause = queryInfo.getOrderByClause();
		}

		if ( whereClause == null || whereClause.length() == 0 ) {
			whereClause = new String();
		}
		if ( orderByClause != null && orderByClause.length() != 0 ) {
			orderByClause = " order by " + orderByClause;
		} else {
			orderByClause = new String();
		}

		List list = null;
		Integer total = null;

		String hqlPart = new String();
		ArrayList args = new ArrayList();
        hqlPart = new StringBuffer("from ForumSubscription as fs ")
                .toString();
        if (whereClause.length() > 0) {
            hqlPart = hqlPart + " where " + whereClause;
        }

		if ( queryInfo != null && queryInfo.getLimit() != null && queryInfo.getOffset() != null ) {
			// query count
			String hqlForTotal = "select count(distinct fs.id) " + hqlPart;
			total = findUniqueIntegerResult(hqlForTotal, args.toArray());
			if ( total == null ) {
				total = new Integer(0);
			}
		}

        // If we don't have any info about the total number of results yet or
        // we know that there's something that will be found, then fetch data
		if ( total == null || total.intValue() > 0 ) {
			String hql = new String();
    		hql = "select fs " + hqlPart + orderByClause;
			list = executeFind(hql, queryInfo, args.toArray());
            if ( total == null ) {
                total = new Integer(list.size());
            }
		} else {
			list = new ArrayList();
		}

		return new PartialCollection(list, total);
    }

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#hasDuplicates(com.blandware.atleap.model.forum.ForumSubscription, Long, Long, String)
     */
    public boolean hasDuplicates(ForumSubscription forumSubscription,
                                 Long forumId, Long topicId, String userName) {
        if (forumId == null && topicId == null) {
            return false;
        }

        boolean isForum = forumId != null;
        String linkCond = isForum ? " fs.forum.id = ? " : " fs.topic.id = ? ";
        Long linkArg = isForum ? forumId : topicId;

        boolean anonymous = userName == null;
        String userCond = anonymous ? " fs.email = ? " : " fs.user.name = ? ";
        Object userArg = anonymous ? forumSubscription.getEmail() : userName;

        String hql = new StringBuffer("select count(fs) from ForumSubscription as fs ")
                .append("where ").append(linkCond)
                .append("and ").append(userCond)
                .toString();
        Integer count = findUniqueIntegerResult(hql, new Object[]{linkArg, userArg});
        return count.intValue() > 0;
    }

    // ~ Finders ================================================================

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#findForumSubscriptionsByForumIdAndUserName(Long, String)
     */
    public List findForumSubscriptionsByForumIdAndUserName(Long forumId,
                                                           String userName) {
        String hql = new StringBuffer("select fs from ForumSubscription as fs ")
                .append("where fs.forum.id = ? ")
                .append("and fs.user.name = ? ")
                .toString();
        return executeFind(hql, new Object[]{forumId, userName});
    }

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#findForumSubscriptionsByTopicIdAndUserName(Long, String)
     */
    public List findForumSubscriptionsByTopicIdAndUserName(Long topicId,
                                                           String userName) {
        String hql = new StringBuffer("select fs from ForumSubscription as fs ")
                .append("where fs.topic.id = ? ")
                .append("and fs.user.name = ? ")
                .toString();
        return executeFind(hql, new Object[]{topicId, userName});
    }

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#findActivatedSubscriptionsByForumIdOrTopicId(Long, Long)
     */
    public List findActivatedSubscriptionsByForumIdOrTopicId(Long forumId,
                                                             Long topicId) {
        if (forumId == null && topicId == null) {
            return null;
        }

        String hql = new StringBuffer("select fs from ForumSubscription as fs ")
                .append("where fs.forum.id = ? or fs.topic.id = ? ")
                .append("and fs.activated = 'T' ")
                .toString();
        return executeFind(hql, new Object[]{forumId, topicId});
    }

    /**
     * @see com.blandware.atleap.persistence.forum.ForumSubscriptionDAO#findTimedOutForumSubscriptions()
     */
    public List findTimedOutForumSubscriptions() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -3);
        String hql = new StringBuffer("select fs from ForumSubscription as fs ")
                .append("where fs.activated = 'F' ")
                .append("and fs.date < ? ")
                .toString();
        return executeFind(hql, new Object[]{calendar.getTime()});
    }
}
